package rtssession

import (
	"gitee.com/general252/gortc/pkg/format"
	"gitee.com/general252/gortc/pkg/rtcsdp"
	"gitee.com/general252/gortc/pkg/streammuxer"
	"gitee.com/general252/gortc/pkg/track"
	"github.com/pion/rtp"
	"log"
	"net"
)

// ServerSessionRTP 绑定一个客户端连接(拉流/推流/双向流)
type ServerSessionRTP struct {
	mediaPath string
	mux       streammuxer.StreamMuxer
	writer    track.RtpRtcpWriter

	addr  net.Addr
	offer *rtcsdp.Session

	pusher *streammuxer.Stream
	puller *streammuxer.Puller
}

func NewServerSessionRTP(mediaPath string, mux streammuxer.StreamMuxer, writer track.RtpRtcpWriter) *ServerSessionRTP {
	return &ServerSessionRTP{
		mediaPath: mediaPath,
		mux:       mux,
		writer:    writer,
	}
}

func (tis *ServerSessionRTP) Close(cause error) {
	if tis.puller != nil {
		_ = tis.mux.RemoteStream(tis.pusher)
	}

	if tis.pusher != nil {
		_ = tis.mux.RemoteStream(tis.pusher)
	}
}

func (tis *ServerSessionRTP) SetRemoteAddr(addr net.Addr) {
	tis.addr = addr
}

func (tis *ServerSessionRTP) OnOffer(offer *rtcsdp.Session) {
	tis.offer = offer

	for _, cm := range offer.Medias {
		if cm.Direction == rtcsdp.DirectionRecvOnly || cm.Direction == rtcsdp.DirectionSendRecv {
			for _, ct := range cm.Formats {
				tis._addReceiver(cm, ct)
			}
		}

		if cm.Direction == rtcsdp.DirectionSendOnly || cm.Direction == rtcsdp.DirectionSendRecv {
			for _, ct := range cm.Formats {
				tis._addSender(cm, ct)
			}
		}
	}
}

func (tis *ServerSessionRTP) _addReceiver(cm *rtcsdp.Media, ct format.Format) {
	var (
		puller   *streammuxer.Puller
		err      error
		streamId = streammuxer.NewStreamIdRTP(cm.SSRC, ct.PayloadType())
	)

	puller, err = tis.mux.AddPull(streamId, streammuxer.PullInfo{
		Name: "",
		OnPacket: func(info *streammuxer.StreamInfo, data *streammuxer.StreamData) {
			switch value := data.Data.(type) {
			case *rtp.Packet:
				pkt := value
				tis._writePacketRTP(pkt)
			}

		},
		OnStreamClose: func(stream *streammuxer.Stream) {
			_ = tis.mux.RemotePull(puller)
		},
	})
	if err != nil {
		log.Println(err)
		return
	}

	tis.puller = puller
}

func (tis *ServerSessionRTP) _addSender(cm *rtcsdp.Media, ct format.Format) {
	streamId := streammuxer.NewStreamIdRTP(cm.SSRC, ct.PayloadType())
	stream, err := tis.mux.AddStream(streammuxer.StreamInfo{
		Id:          streamId,
		Name:        "",
		OnNewPuller: nil,
		OnDelPuller: nil,
	})
	if err != nil {
		log.Println(err)
		return
	}

	tis.pusher = stream
}

func (tis *ServerSessionRTP) _writePacketRTP(pkt *rtp.Packet) {
	// pkt.SSRC = 123 // 修改ssrc
	_ = tis.writer.WriteRTP(pkt, tis.addr)
}
